#![allow(unused_must_use)]

use std::collections::HashMap;
use std::env;

#[derive(Clone)]
pub struct Flag {
    pub key: String,
    pub value: String,
    pub chile_flags: Option<Vec<Flag>>,
}

// impl std::clone::Clone for Flag{
//     fn clone(&mut self) -> Self{
//         Flag{
//             key:self.key.clone(),
//             value:self.value.clone(),
//             chile_flags:self.chile_flags.clone(),
//         }
//     }
//     fn clone_from(&mut self, source: &Self) {
//         *self = Flag{
//             key:source.key.clone(),
//             value:source.value.clone(),
//             chile_flags:source.chile_flags.clone(),
//         }
//     }
// }

#[derive(Clone)]
pub struct FlagTree {
    pub name: String,
    pub global: HashMap<String, Flag>,
    pub flags: HashMap<String, Flag>,
}

// impl std::clone::Clone for FlagTree{
//     fn clone(&mut self) -> Self{
//         FlagTree{
//             name:self.name.clone(),
//             global:self.global.clone(),
//             flags: self.flags.clone(),
//         }
//     }
//     fn clone_from(&mut self, source: &Self) {
//         *self = FlagTree{
//             name:source.name.clone(),
//             global:source.global.clone(),
//             flags: source.flags.clone(),
//         }
//     }
// }

impl FlagTree {
    fn add_global(&mut self, key: String, value: String) {
        let flag = Flag {
            key: key.clone(),
            value: value.clone(),
            chile_flags: None,
        };
        self.global.insert(key, flag);
    }
    #[allow(dead_code)]
    fn add_cmd(&mut self, key: String) {
        let flag = Flag {
            key: key.clone(),
            value: "-".to_string(),
            chile_flags: None,
        };
        self.flags.insert(key, flag);
    }
    fn add_flags(&mut self, group: &String, key: String, value: String) {
        if group == "-" {
            self.add_global(key, value);
            return;
        }
        let flag = Flag {
            key: key.clone(),
            value: value.clone(),
            chile_flags: None,
        };
        if let None = self.flags.get(group) {
            self.flags.insert(key, flag);
        } else if let Some(parent) = self.flags.get_mut(group) {
            match &mut parent.chile_flags {
                None => {
                    parent.chile_flags = Some(vec![flag]);
                }
                Some(p) => {
                    p.push(flag);
                }
            }
        }
    }
    #[allow(dead_code)]
    pub fn print(&self) {
        print!("\n");
        println!("The running program is: {}", self.name);
        if self.global.len() > 0 {
            print!("\n");
            println!("global parameters:");
        }
        for (_, y) in self.global.iter() {
            println!("  ->name:{} value:{}", y.key, y.value);
        }
        self.flags.iter().for_each(|(_, y)| {
            print!("\n");
            println!("existing input command:{}", y.key);
            if let Some(flags) = &y.chile_flags {
                flags.iter().for_each(|f| {
                    println!("  ->name:{} value:{}", f.key, f.value);
                });
            }
        });
    }
}

pub fn load() -> Result<FlagTree, &'static str> {
    let args: Vec<String> = env::args().collect();
    let mut ft = FlagTree {
        name: args[0].clone(),
        global: HashMap::new(),
        flags: HashMap::new(),
    };
    let mut group = "-".to_string();
    let mut i = 1;
    while i < args.len() {
        let cmd = args[i].clone();
        if &cmd[0..1] == "-" {
            let mut value: String = "-".to_string();
            if i < args.len() - 1 {
                if &args[i + 1][0..1] != "-" {
                    value = args[i + 1].clone();
                    i += 1;
                }
            }
            ft.add_flags(&group, cmd, value)
        } else {
            ft.add_cmd(cmd.clone());
            group = cmd;
        }
        i += 1;
    }
    return Ok(ft);
}
